home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODECS.ZIP / codecs / english / codrle4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-13  |  7.8 KB  |  201 lines

  1. /* File: codrle4.c
  2.    Author: David Bourgin
  3.    Creation date: 1/2/94
  4.    Last update: 24/7/95
  5.    Purpose: Example of RLE type 4 encoding with a file source to compress.
  6. */
  7.  
  8. #include <stdio.h>
  9. /* For routines printf,fputc,fread and fwrite */
  10. #include <memory.h>
  11. /* For routine memcpy */
  12. #include <stdlib.h>
  13. /* For routine exit */
  14.  
  15. /* Error codes sent to the caller */
  16. #define NO_ERROR      0
  17. #define BAD_FILE_NAME 1
  18. #define BAD_ARGUMENT  2
  19.  
  20. /* Useful constants */
  21. #define FALSE 0
  22. #define TRUE  1
  23.  
  24. #define MAX_FRAME_SIZE 65
  25.  
  26. /* Global variables */
  27. FILE *source_file,*dest_file;
  28.  
  29. unsigned int index=0,
  30.              buffer_read_size=0;
  31. unsigned char buffer_read[8224+2*65];
  32.  
  33. typedef struct { unsigned int array_size;
  34.                  unsigned char *array_val;
  35.                } t_tab;
  36. #define ARRAY_SIZE(array)  ((array).array_size)
  37. #define ARRAY_VAL(array)  ((array).array_val)
  38. #define ARE_EQUAL(array1,array2)  ((ARRAY_SIZE(array1)==ARRAY_SIZE(array2))&&(!memcmp(ARRAY_VAL(array1),ARRAY_VAL(array2),ARRAY_SIZE(array1))))
  39.  
  40. /* Pseudo procedures */
  41. #define load_block()  { buffer_read_size=fread(buffer_read,1,sizeof(buffer_read),source_file); index=0; }
  42. #define move_index(i)  (index=(i))
  43. #define size_remaining_to_read()  (buffer_read_size-index)
  44. #define read_array(array,nb_to_read)  { ARRAY_SIZE(array)=(nb_to_read);\
  45.                                         ARRAY_VAL(array)= &(buffer_read[index]);\
  46.                                         index += (nb_to_read);\
  47.                                       }
  48. #define write_byte(x)  ((void)fputc((unsigned char)(x),dest_file))
  49. #define write_word(x)  { write_byte((x) >> 8); write_byte((x) & 0xFF); }
  50. #define write_array(array)  ((void)fwrite(ARRAY_VAL(array),1,ARRAY_SIZE(array),dest_file))
  51. #define fill_block()  { (void)memcpy(buffer_read,&(buffer_read[index]),size_remaining_to_read());\
  52.                         buffer_read_size=fread(&(buffer_read[size_remaining_to_read()]),1,sizeof(buffer_read)-size_remaining_to_read(),source_file)+size_remaining_to_read();\
  53.                         index=0;\
  54.                       }
  55.  
  56. void rle4look_for_occurr(basic_index,frame_nb,frame_size,
  57.                          repetition_ok)
  58. /* Returned parameters: 'frame_nb', 'frame_size' and 'repetition_ok' are modified
  59.    Action: Looks in the byte buffer if there's a frame repetition from 'basic_index' position
  60.    where size and repetition are respectively in 'frame_size' and 'frame_nb'.
  61.    Whenever a repetition is met, 'repetition_ok' returns 'TRUE' otherwise 'repetition_ok' returns 'FALSE'
  62.    Errors: Whenever there are no multiple frames then 'frame_nb' won't be modified
  63. */
  64. unsigned int basic_index,*frame_nb,*frame_size;
  65. int *repetition_ok;
  66. { int array_equality;
  67.   t_tab array1,array2;
  68.  
  69.   *frame_size=1;
  70.   *repetition_ok=FALSE;
  71.   move_index(basic_index);
  72.   while ((*frame_size<=MAX_FRAME_SIZE)&&(size_remaining_to_read()>=(*frame_size << 1))&&(!*repetition_ok))
  73.         { read_array(array1,*frame_size);
  74.           read_array(array2,*frame_size);
  75.           if (array_equality=ARE_EQUAL(array1,array2))
  76.              { *frame_nb=2;
  77.                while ((size_remaining_to_read()>=*frame_size)
  78.                       &&(((*frame_nb<16449)&&(*frame_size==1))||((*frame_nb<257)&&(*frame_size>1)))
  79.                       &&(array_equality))
  80.                      { if ((*frame_size>2)||(*frame_nb>2))
  81.                           { if (*repetition_ok)
  82.                                move_index(*frame_size);
  83.                             else { *repetition_ok=TRUE;
  84.                                    if (basic_index)
  85.                                       return;
  86.                                    move_index((*frame_nb-1)*(*frame_size));
  87.                                  }
  88.                             fill_block();
  89.                             move_index(*frame_size);
  90.                           }
  91.                        read_array(array2,*frame_size);
  92.                        if (array_equality=ARE_EQUAL(array1,array2))
  93.                           (*frame_nb)++;
  94.                      }
  95.                if ((*frame_size>2)||(*frame_nb>2))
  96.                   { if (basic_index)
  97.                        { *repetition_ok=TRUE;
  98.                          return;
  99.                        }
  100.                     if (*repetition_ok)
  101.                        {  if (array_equality)
  102.                              { move_index(*frame_size);
  103.                                fill_block();
  104.                              }
  105.                        }
  106.                     else { *repetition_ok=TRUE;
  107.                            move_index((*frame_nb-1)*(*frame_size));
  108.                            fill_block();
  109.                          }
  110.                     (*frame_size)--;
  111.                   }
  112.                              /* Specifies to the caller there was a repetition */
  113.              }
  114.           (*frame_size)++;
  115.           move_index(basic_index);
  116.         }
  117. }
  118.  
  119. void rle4encoding()
  120. /* Returned parameters: None
  121.    Action: Compresses with RLE type 4 method all bytes read by the function read_byte
  122.    Errors: An input/output error could disturb the running of the program
  123. */
  124. { t_tab frame;
  125.   unsigned int frame_nb1,frame_size1,frame_nb2,frame_size2;
  126.   int repetition_valid;
  127.  
  128.   load_block();
  129.   while (size_remaining_to_read())
  130.         { rle4look_for_occurr(0,&frame_nb1,&frame_size1,&repetition_valid);
  131.           if (repetition_valid)
  132.                              /* Was there a repetition? */
  133.              { if (frame_size1==1)
  134.                              /* Frame of 1 byte? */
  135.                   { if (frame_nb1<66)
  136.                              /* Frame with a byte but less than 66 times? */
  137.                        write_byte(frame_nb1-2);
  138.                     else write_word(frame_nb1+16318);
  139.                   }
  140.                else {        /* Frame with several bytes */
  141.                       write_byte(frame_size1+126);
  142.                       write_byte(frame_nb1-2);
  143.                     }
  144.              }
  145.           else { frame_size1=0;
  146.                  do {        /* Tests until where there's no repetition */
  147.                       frame_size1++;
  148.                       rle4look_for_occurr(frame_size1,&frame_nb2,&frame_size2,&repetition_valid);
  149.                     }
  150.                  while ((size_remaining_to_read())&&(frame_size1<8224)&&(!repetition_valid));
  151.                  if (frame_size1<33)
  152.                              /* Non repetition of a frame with less than 33 Bytes */
  153.                     write_byte(frame_size1+191);
  154.                  else write_word(frame_size1+57311);
  155.                }
  156.           move_index(0);
  157.           read_array(frame,frame_size1);
  158.           write_array(frame);
  159.           fill_block();      /* All new analysis must start at 0 in the buffer */
  160.         }
  161. }
  162.  
  163. void help()
  164. /* Returned parameters: None
  165.    Action: Displays the help of the program and then stops its running
  166.    Errors: None
  167. */
  168. { printf("This utility enables you to compress a file by using RLE type 4 method\n");
  169.   printf("as given in 'La Video et Les Imprimantes sur PC'\n");
  170.   printf("\nUse: codrle4 source target\n");
  171.   printf("source: Name of the file to compress\n");
  172.   printf("target: Name of the compressed file\n");
  173. }
  174.  
  175. int main(argc,argv)
  176. /* Returned parameters: Returns an error code (0=None)
  177.    Action: Main procedure
  178.    Errors: Detected, handled and an error code is returned, if any
  179. */
  180. int argc;
  181. char *argv[];
  182. { if (argc!=3)
  183.      { help();
  184.        exit(BAD_ARGUMENT);
  185.      }
  186.   else if ((source_file=fopen(argv[1],"rb"))==NULL)
  187.           { help();
  188.             exit(BAD_FILE_NAME);
  189.           }
  190.        else if ((dest_file=fopen(argv[2],"wb"))==NULL)
  191.                { help();
  192.                  exit(BAD_FILE_NAME);
  193.                }
  194.             else { rle4encoding();
  195.                    fclose(source_file);
  196.                    fclose(dest_file);
  197.                  }
  198.   printf("Execution of codrle4 completed.\n");
  199.   return (NO_ERROR);
  200. }
  201.